// run: time $exec < input
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <utility>

int const inf = 1 << 28;
int const maxn = 100007;
int const maxq = 16;
bool centroid[maxn];
int subtree_size[maxn];
int xor_p[1<<17];
int query_input[maxq];
long long ans[maxq];
int n, m;

typedef std::pair<int, int> node_type;
typedef std::vector<node_type> adj_edge;
typedef adj_edge::iterator edge_iter;

#define HUGE_INPUT

adj_edge graph[maxn];

std::vector<int> count;
std::vector<int> tmp_count;

int calc_subtree_size(int u, int parent)
{
	int sum = 1;

	for (int i = 0; i < (int)graph[u].size(); i++) {
		int v = graph[u][i].first;
	//for (edge_iter it = graph[u].begin(); it != graph[u].end(); ++it) {
	//	int v = it->first;
		if (centroid[v] || parent == v) continue;
		sum += calc_subtree_size(v, u);
	}
	return subtree_size[u] = sum;
}

std::pair<int, int> get_center(int u, int parent, int all)
{
	std::pair<int, int> center(inf, -1);
	int sum = 1, max_sub = 0;

	for (int i = 0; i < (int)graph[u].size(); i++) {
		int v = graph[u][i].first;
	//for (edge_iter it = graph[u].begin(); it != graph[u].end(); ++it) {
	//	int v = it->first;
		if (centroid[v] || parent == v) continue;
		max_sub = std::max(max_sub, subtree_size[v]);
		sum += subtree_size[v];
		center = std::min(center, get_center(v, u, all));
	}
	max_sub = std::max(max_sub, all - sum);
	return std::min(center, std::make_pair(max_sub, u));
}

void calc_dis_to_center(int u, int parent, int dis)
{
	tmp_count.push_back(dis);

	for (int i = 0; i < (int)graph[u].size(); i++) {
		int v = graph[u][i].first, c = graph[u][i].second;
	//for (edge_iter it = graph[u].begin(); it != graph[u].end(); ++it) {
	//	int v = it->first, c = it->second;
		if (centroid[v] || parent == v) continue;
		calc_dis_to_center(v, u, dis ^ c);
	}
}

void calc_pair(std::vector<int> & count, int opt)
{
	for (int i = 0; i < (int)count.size(); i++) xor_p[count[i]]++;
	for (int i = 0; i < (int)count.size(); i++)
		for (int ti = 0; ti < m; ti++)
			ans[ti] = ans[ti] + opt * xor_p[count[i] ^ query_input[ti]];
	for (int i = 0; i < (int)count.size(); i++) xor_p[count[i]]--;
}

void divide_and_conquer_for_tree(int u)
{
	calc_subtree_size(u, -1);
	int center = get_center(u, -1, subtree_size[u]).second;
	centroid[center] = true;

	for (int i = 0; i < (int)graph[center].size(); i++) {
		int v = graph[center][i].first;
	//for (edge_iter it = graph[center].begin(); it != graph[center].end(); ++it) {
	//	int v = it->first;
		if (centroid[v]) continue;
		divide_and_conquer_for_tree(v);
	}

	count.clear();
	count.push_back(0);
	for (int i = 0; i < (int)graph[center].size(); i++) {
		int v = graph[center][i].first, c = graph[center][i].second;
	//for (edge_iter it = graph[center].begin(); it != graph[center].end(); ++it) {
	//	int v = it->first, c = it->second;
		if (centroid[v]) continue;
		tmp_count.clear();
		calc_dis_to_center(v, center, c);
		/*
		for (int qi = 0; qi < m; qi++)
			ans[qi] -= calc_pair(tmp_count, query_input[qi]);
		*/
		calc_pair(tmp_count, -1);
		count.insert(count.end(), tmp_count.begin(), tmp_count.end());
	}
	calc_pair(count, 1);
	/*
	for (int qi = 0; qi < m; qi++)
		ans[qi] += calc_pair(count, query_input[qi]);
	*/
	centroid[center] = false;
}

void scan(int & a)
{
	a = 0;
	bool flag = false;
	char ch = std::getchar();
	if (ch == '-')
		flag = true;
	else if (ch >= '0' && ch <= '9')
		a = ch - '0';

	while ((ch = std::getchar()) >= '0' && ch <= '9')
		a = a * 10 + ch - '0';
	if (flag) a = -a;
}

int main()
{
	int T; scan(T);
	while (T--) {
		scan(n);
		for (int i = 0; i < n; i++) graph[i].clear();
		for (int i = 1, x, y; i < n; i++) {
			node_type tmp;
			scan(x); x--;
			scan(y); y--;
			scan(tmp.second);
			tmp.first = y; graph[x].push_back(tmp);
			tmp.first = x; graph[y].push_back(tmp);
		}

		scan(m);
		for (int i = 0; i < m; i++) {
			scan(query_input[i]);
			ans[i] = 0;
		}

		std::memset(xor_p, 0, sizeof(xor_p));
		divide_and_conquer_for_tree(0);
		for (int i = 0; i < m; i++)
			std::printf("%I64d\n", ans[i] / 2); // FIXME
	}
}

